package com.sinooceangroup.voiceassistant;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.iflytek.aiui.AIUIConstant;
import com.iflytek.aiui.AIUIEvent;
import com.iflytek.aiui.AIUIListener;
import com.iflytek.aiui.AIUIMessage;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.AndPermission;
import com.yanzhenjie.permission.Permission;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 语音助手对话界面
 */
public class VoiceAssistantActivity extends Activity implements View.OnClickListener {

    public interface Callback {
        void onResp(String result);
    }

    private static Callback callback;

    //入口方法
    public static void startActivity(Activity activity, Callback callback) {
        VoiceAssistantActivity.callback = callback;
        activity.startActivity(new Intent(activity, VoiceAssistantActivity.class));
        activity.overridePendingTransition(R.anim.activity_up_in, R.anim.activity_anim_no);
    }


    private static final String TAG = "VoiceAssistantActivity";
    private ListView listView;
    private WaveLineView waveLineView;
    private List<VoiceModel> chatListData = new ArrayList<>();

    private VoiceAssistantAdapter adapter;
    private ImageView ivClose, ivKeyboard;

    private RelativeLayout rlRecord;
    private LinearLayout llText;

    private ImageView ivRecord, ivSettings;
    private Button btnSend;
    private EditText etText;


    private final String helloMessage = "你好，我是小洋，\n有什么可以帮你的吗？";
    private boolean isHello = true;
    private Toast mToast;
    LinearLayout footerView;


    private void showTip(final String str) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mToast.setText(str);
                mToast.show();
            }
        });
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = getWindow();
            //设置修改状态栏
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            //设置状态栏的颜色，和你的app主题或者标题栏颜色设置一致就ok了
            window.setStatusBarColor(Color.WHITE);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        }
        EventBus.getDefault().register(this);
        setContentView(R.layout.activity_voice_assistant);
        initView();
        setListener();
    }

    @Override
    protected void onPause() {
        super.onPause();
        AIUIManager.getInstance().stopTTS();
    }

    private void initView() {
        mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
        listView = (ListView) findViewById(R.id.recyclerView);
        waveLineView = (WaveLineView) findViewById(R.id.waveLineView);
        ivClose = (ImageView) findViewById(R.id.ivClose);
        ivKeyboard = (ImageView) findViewById(R.id.ivKeyboard);
        adapter = new VoiceAssistantAdapter(chatListData, this);
        listView.setAdapter(adapter);
        footerView = (LinearLayout) getLayoutInflater().inflate(R.layout.adapter_voice_assistant_footer, null);
        footerView.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, ListView.LayoutParams.MATCH_PARENT));
        listView.addFooterView(footerView);
        rlRecord = (RelativeLayout) findViewById(R.id.rlRecord);
        llText = (LinearLayout) findViewById(R.id.llText);
        ivRecord = (ImageView) findViewById(R.id.ivRecord);
        btnSend = (Button) findViewById(R.id.btnSend);
        etText = (EditText) findViewById(R.id.etText);
        ivSettings = (ImageView) findViewById(R.id.ivSetting);

    }


    int listViewLayoutHeight = 0;

    private void setVoidHeight() {
        if (AIUIManager.getInstance().isAudioRecording()) {
            footerView.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, listViewLayoutHeight-adapter.getItemHeight(chatListData.size() - 1)));
        } else {
            if (!chatListData.get(chatListData.size() - 1).isUser()) {
                int lastItemHeight = adapter.getItemHeight(chatListData.size() - 2) + adapter.getItemHeight(chatListData.size() - 1);
                if (lastItemHeight > listViewLayoutHeight) {
                    footerView.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, 0));
                } else {
                    footerView.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, listViewLayoutHeight - lastItemHeight));
                }
            }
        }
    }


    private void setListener() {
        ivClose.setOnClickListener(this);
        ivRecord.setOnClickListener(this);
        ivKeyboard.setOnClickListener(this);
        waveLineView.setOnClickListener(this);
        btnSend.setOnClickListener(this);
        etText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (TextUtils.isEmpty(s)) {
                    btnSend.setBackgroundResource(R.drawable.bg_button_send_unenable);
                    btnSend.setEnabled(false);
                } else {
                    btnSend.setBackgroundResource(R.drawable.bg_button_send_enable);
                    btnSend.setEnabled(true);
                }
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
        ivSettings.setOnClickListener(this);

        listView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                listViewLayoutHeight = bottom - top;
                setVoidHeight();
            }
        });

    }


    @Override
    protected void onResume() {
        super.onResume();
        AndPermission.with(this)
                .permission(Permission.RECORD_AUDIO, Permission.READ_PHONE_STATE, Permission.WRITE_EXTERNAL_STORAGE, Permission.ACCESS_FINE_LOCATION)
                .onGranted(new Action() {
                    @Override
                    public void onAction(List<String> permissions) {
                        if (chatListData.size() == 0) {
                            AIUIManager.getInstance().initAIUI(getApplicationContext(), mAIUIListener);
                            AIUIManager.getInstance().wakeupAIUI();
                            chatListData.add(new VoiceModel(false, helloMessage));
                            adapter.notifyDataSetChanged();
                            AIUIManager.getInstance().startTTS(helloMessage);
                        }
                    }
                })
                .onDenied(new Action() {
                    @Override
                    public void onAction(List<String> permissions) {
                        Toast.makeText(VoiceAssistantActivity.this, "请前往设置给应用授权", Toast.LENGTH_SHORT).show();
                    }
                }).start();
    }


    private void start() {

        isHello = false;
        if (AIUIManager.getInstance().isAudioRecording()) {
            AIUIManager.getInstance().stopTTS();
            AIUIManager.getInstance().stopRecordAudio();
            AIUIManager.getInstance().setAudioRecording(false);
            waveLineView.reset();
            ivKeyboard.setVisibility(View.VISIBLE);
        } else {
            chatListData.add(new VoiceModel(true, "", true));
            adapter.notifyDataSetChanged();
            hideKeyboard(etText);
            setVoidHeight();
            AIUIManager.getInstance().stopTTS();
            waveLineView.startRecord();
            AIUIManager.getInstance().startRecordAudio("" + chatListData.size());
            ivKeyboard.setVisibility(View.INVISIBLE);
        }
    }

    @Override
    public void onClick(View v) {
        //在Library中switch case不能使用R.id.xx 因为Library生成的R.id.xx不是常量
        int id = v.getId();
        if (id == R.id.waveLineView) {
            start();
        } else if (id == R.id.ivClose) {
            AIUIManager.getInstance().stopTTS();
            AIUIManager.getInstance().sendMessage(new AIUIMessage(AIUIConstant.CMD_WRITE, 0, 0, "data_type=text", "退出".getBytes()));
            waveLineView.stopRecord();
            waveLineView.stopAnim();
            finish();
            overridePendingTransition(R.anim.activity_anim_no, R.anim.activity_down_out);
        } else if (id == R.id.ivKeyboard) {
            rlRecord.setVisibility(View.GONE);
            waveLineView.setVisibility(View.GONE);
            llText.setVisibility(View.VISIBLE);
            showKeyboard(etText);
        } else if (id == R.id.btnSend) {
            listView.smoothScrollToPosition(chatListData.size());
            chatListData.add(new VoiceModel(true, etText.getText().toString()));
            byte[] content = etText.getText().toString().getBytes();
            AIUIManager.getInstance().sendMessage(new AIUIMessage(AIUIConstant.CMD_WRITE, 0, 0, "data_type=text,tag=" + chatListData.size(), content));
            etText.setText("");
        } else if (id == R.id.ivRecord) {
            rlRecord.setVisibility(View.VISIBLE);
            waveLineView.setVisibility(View.VISIBLE);
            waveLineView.startAnim();
            llText.setVisibility(View.GONE);
            hideKeyboard(etText);
        } else if (id == R.id.ivSetting) {
            startActivity(new Intent(this, SettingsActivity.class));
        }
    }


    AIUIListener mAIUIListener = new AIUIListener() {

        @Override
        public void onEvent(AIUIEvent event) {
            switch (event.eventType) {
                //唤醒事件
                case AIUIConstant.EVENT_WAKEUP:
//                    Log.i(TAG, "唤醒事件 on event: " + event.eventType);
                    break;
                //结果事件（包含听写，语义，离线语法结果）
                case AIUIConstant.EVENT_RESULT:
                    //结果解析事件
                    try {
                        JSONObject bizParamJson = new JSONObject(event.info);
                        JSONObject data = bizParamJson.getJSONArray("data").getJSONObject(0);
                        JSONObject params = data.getJSONObject("params");
                        JSONObject content = data.getJSONArray("content").getJSONObject(0);
                        String cnt_id = content.getString("cnt_id");
                        String cntStr = new String(Objects.requireNonNull(event.data.getByteArray(cnt_id)), StandardCharsets.UTF_8);
                        JSONObject cntJson;
                        switch (params.optString("sub")) {
                            case "iat"://听写结果
                            {
//                                Log.i(TAG, "听写结果 event.info:" + event.info);
//                                Log.i(TAG, "听写结果 event.data:" + cntStr);

                                cntJson = new JSONObject(cntStr);
                                StringBuilder resultStr = new StringBuilder();

                                JSONArray jsonArray = cntJson.getJSONObject("text").getJSONArray("ws");
                                for (int i = 0; i < jsonArray.length(); i++) {
                                    resultStr.append(jsonArray.getJSONObject(i).getJSONArray("cw").getJSONObject(0).getString("w"));
                                }

                                if (!TextUtils.isEmpty(resultStr.toString())) {
                                    if (chatListData.get(chatListData.size() - 1).isDictation()) {
                                        chatListData.get(chatListData.size() - 1).setMessage(resultStr.toString());
                                    }
                                }
                                adapter.notifyDataSetChanged();
                                boolean lastResult = cntJson.getJSONObject("text").optBoolean("ls");
                                AIUIManager.getInstance().setAudioRecording(!lastResult);
                                if (lastResult) {
                                    waveLineView.stopRecord();
                                    chatListData.get(chatListData.size() - 1).setDictation(false);
                                }

                            }
                            break;
                            case "nlp"://语义结果
                                int tag;
                                if (event.data.getString("tag") != null && !"".equals(event.data.getString("tag")) && event.data.getString("tag").matches("^[0-9]*$"))
                                    tag = Integer.parseInt(event.data.getString("tag"));
                                else
                                    tag = chatListData.size();
                                cntJson = new JSONObject(cntStr);
                                JSONObject semanticResult = cntJson.optJSONObject("intent");
                                String text = "";
                                if (semanticResult != null && semanticResult.length() != 0) {
                                    //解析得到语义结果，将语义结果作为消息插入到消息列表中
                                    if (semanticResult.has("answer") && semanticResult.getJSONObject("answer").has("text")) {
                                        text = semanticResult.getJSONObject("answer").getString("text");
                                        if (tag + 1 == chatListData.size()) {
                                            chatListData.add(new VoiceModel(false, text));
                                            adapter.notifyDataSetChanged();
                                            AIUIManager.getInstance().startTTS(text);
                                        } else {
                                            chatListData.add(tag , new VoiceModel(false, text));
                                            adapter.notifyDataSetChanged();
//                                            AIUIManager.getInstance().startTTS(text);
                                        }

                                    }
                                }

                                waveLineView.reset();
                                ivKeyboard.setVisibility(View.VISIBLE);
                                if (callback != null)
                                    callback.onResp(cntStr);
                                break;
                        }
                    } catch (Throwable e) {
                        e.printStackTrace();
                    }
                    break;
                //休眠事件
                case AIUIConstant.EVENT_SLEEP:
                    Log.i(TAG, "休眠事件 on event: " + event.eventType);
                    AIUIManager.getInstance().stopTTS();
                    AIUIManager.getInstance().stopRecordAudio();
                    AIUIManager.getInstance().setAudioRecording(false);
                    waveLineView.reset();
                    ivKeyboard.setVisibility(View.VISIBLE);
                    break;
                // 状态事件
                case AIUIConstant.EVENT_STATE:
                    AIUIManager.getInstance().setAIUIState(event.arg1);
                    if (AIUIConstant.STATE_IDLE == event.arg1) {
                        // 闲置状态，AIUI未开启
                    } else if (AIUIConstant.STATE_READY == event.arg1) {
                        // AIUI已就绪，等待唤醒
                    } else if (AIUIConstant.STATE_WORKING == event.arg1) {
                        // AIUI工作中，可进行交互
                    }
                    break;
                //错误事件
                case AIUIConstant.EVENT_ERROR:
                    Log.i(TAG, "on event: " + event.eventType);
                    Log.e(TAG, "错误: " + event.arg1 + "\n" + event.info);
                    int errorCode = event.arg1;
                    if (errorCode == 20006) {
                        AIUIManager.getInstance().setAudioRecording(false);
                    }
                    //错误停止
                    waveLineView.reset();
                    ivKeyboard.setVisibility(View.VISIBLE);
                    break;
                case AIUIConstant.EVENT_VAD:
//                    Log.i(TAG, "on event: " + event.eventType);
                    //当arg1取值为1时，arg2为音量大小。
//                    Log.i(TAG, "on 音量: " + event.arg2);
                    if (event.arg1 == 1) {
                        waveLineView.setVolume(event.arg2);
                    }
                    if (AIUIConstant.VAD_BOS == event.arg1) {
                        //语音前端点
                    } else if (AIUIConstant.VAD_EOS == event.arg1) {
                        //语音后端点
                    }
                    break;
                //开始录音
                case AIUIConstant.EVENT_START_RECORD:
//                    Log.i(TAG, "开始录音 on event: " + event.eventType);
                    listView.smoothScrollToPosition(chatListData.size());
                    break;
                // 停止录音
                case AIUIConstant.EVENT_STOP_RECORD:
//                    Log.i(TAG, "停止录音 on event: " + event.eventType);
                    break;
                case AIUIConstant.EVENT_CONNECTED_TO_SERVER:
//                    showTip("已连接服务器");
                    break;

                case AIUIConstant.EVENT_SERVER_DISCONNECTED:
//                    showTip("与服务器断连");
                    break;
                case AIUIConstant.EVENT_TTS: {
                    switch (event.arg1) {
                        case AIUIConstant.TTS_SPEAK_BEGIN://开始播放
                            break;
                        case AIUIConstant.TTS_SPEAK_PROGRESS:// 播放进度
                            break;
                        case AIUIConstant.TTS_SPEAK_PAUSED://暂停播放
                            break;
                        case AIUIConstant.TTS_SPEAK_RESUMED://恢复播放
                            break;
                        case AIUIConstant.TTS_SPEAK_COMPLETED://播放完成
                            if (isHello) {
                                start();
                            } else {

                            }
                            break;

                        default:
                            break;
                    }
                }
                break;
                default:
                    break;
            }
        }
    };


    public void showKeyboard(View view) {
        InputMethodManager imm = (InputMethodManager) view.getContext()
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm != null) {
            view.requestFocus();
            imm.showSoftInput(view, 0);
        }
    }

    public void hideKeyboard(View view) {
        InputMethodManager imm = (InputMethodManager) view.getContext()
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm != null) {
            imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    }


    @Subscribe(threadMode = ThreadMode.ASYNC)
    public void setMessageEvent(Object message) {
        Log.i(TAG, "收到消息:" + message.toString());
        if (!(message instanceof String)) {
            return;
        }
        if (message.equals("close")) {
            AIUIManager.getInstance().sendMessage(new AIUIMessage(AIUIConstant.CMD_WRITE, 0, 0, "data_type=text", "退出".getBytes()));
            finish();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
        AIUIManager.getInstance().getAIUIAgent().destroy();
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        AIUIManager.getInstance().sendMessage(new AIUIMessage(AIUIConstant.CMD_WRITE, 0, 0, "data_type=text", "退出".getBytes()));
    }
}
